#include "std.h"
#include "http.h"

char *web_root = "www";

// http_write_chunk(fw, "hello", 5)
// 共发送 3+5+2 个字符
// 5\r\nHELLO\r\n
void http_write_chunk(FILE *fw, void *chunk, int size)
{
    fprintf(fw, "%x\r\n", size);
    fwrite(chunk, size, 1, fw);
    fprintf(fw, "\r\n");
}

// 共发送 3+0+2 个字符
// 0\r\n\r\n
void http_end(FILE *fw)
{
    http_write_chunk(fw, NULL, 0);
    fflush(fw);
}

void http_prints(FILE *fw, void *string)
{
    int size = strlen(string);
    http_write_chunk(fw, string, size);
}

void http_printf(FILE *fw, const char *format, ...)
{
    va_list ap;
    va_start(ap, format);
    char chunk[100];
    int size = vsprintf(chunk, format, ap);
    va_end(ap);

    http_write_chunk(fw, chunk, size);
}

void http_send_headers(FILE *fp, char *content_type)
{
    fprintf(fp, "HTTP/1.1 200 OK\r\n");
    fprintf(fp, "Server: tiny httpd\r\n");
    fprintf(fp, "Content-type: %s\r\n", content_type);
    fprintf(fp, "Transfer-Encoding: chunked\r\n");
    fprintf(fp, "\r\n");
}

// GET /index.html HTTP/1.1\r\n
char *http_parse_req(FILE *fr, char *req, int req_size)
{
    fgets(req, req_size, fr); 
    puts(req);

    char head[16];
    char *aim = malloc(128);
    char end[16];
    sscanf(req, "%s %s %s", head, aim, end);
    if(strcmp(aim, "/") == 0)
	    strcpy(aim, "/index.html");

    return aim;
}

void write_file(FILE *fw, char *path)
{
	FILE  *file = fopen(path, "r");

	char line[256];
	while(fgets(line ,sizeof(line), file))
		http_prints(fw, line);
	fclose(file);
}

void write_dir(FILE *fw, char *path)
{
	//write_file(fw, "dir.html");

	char new_path[4096];
	http_prints(fw, "<html>\n");

	bzero(new_path, sizeof(new_path));
	sprintf(new_path, "%s%s%s", "<head><title>Index of ", path, "</title></head>");
	http_prints(fw, new_path);
	http_prints(fw, "\n");

	http_prints(fw, "<body>\n");

	bzero(new_path, sizeof(new_path));
	sprintf(new_path, "%s%s%s", "<h1>Index of ", path, "</h1>");
	http_prints(fw, new_path);
	http_prints(fw, "\n");

	http_prints(fw, "<hr>\n");

	char parent[128];

	int t;
	int sum = 0;
	int temp = 0;
	for(t = 0; t < strlen(path); t++) {
		if(path[t] == '/') sum += 1;
	}
	for(t = 0; t < strlen(path); t++) {
		if(path[t] == '/')
			temp += 1;
		if(temp == sum) break;
		parent[t] = path[t];
	}
	if(sum == 1) strcpy(parent, "/");

	bzero(new_path, sizeof(new_path));
	sprintf(new_path, "%s%s%s", "<a href=\"", parent, "\">Parent dir</a><br>");
	http_prints(fw, new_path);
	http_prints(fw, "\n");
	
	char *R_path = malloc(128);
	sprintf(R_path, "%s%s", web_root, path);
	DIR *dir = opendir(R_path);
	struct dirent *entry;
	while(entry = readdir(dir)) {
		if(strcmp(entry->d_name, ".") == 0) 
			continue;
		if(strcmp(entry->d_name, "..") == 0)
			continue;

		char head[32] = "<a href=\"";
		char temp[4096];
		char mid[16] = "\">";
		char end[16] = "</a><br>";
		bzero(temp, sizeof(temp));
		bzero(new_path, sizeof(new_path));
		sprintf(temp, "%s/%s", path, entry->d_name);
		sprintf(new_path, "%s%s%s%s%s", head, temp, mid, entry->d_name, end);
		http_prints(fw, new_path);
		http_prints(fw, "\n");
	}
	closedir(dir);

	http_prints(fw, "<hr>\n");
	http_prints(fw, "</body>\n");
	http_prints(fw, "</html>\n");
}

void http_handler(int fd)
{
    FILE *fr = fdopen(fd, "r");
    FILE *fw = fdopen(fd, "w");

    char req[1024];
    char *http_path;
    http_path = http_parse_req(fr, req, sizeof(req));

/*#if 
    http_send_headers(fw, "text/html");
#else
    http_send_headers(fw, "text/plain");
#endif*/

    //http_prints(fw, "<h1>HELLO</h1>");
    
    char new_path[128];
    bzero(new_path, sizeof(new_path));
    sprintf(new_path, "%s%s", web_root, http_path);

    struct stat info;
    stat(new_path, &info);

    if(S_ISDIR(info.st_mode)) {
	    http_send_headers(fw, "text/html");
	    write_dir(fw, http_path);
    }
    else {
	    if(strstr(new_path, ".html") != NULL)
		    http_send_headers(fw, "text/html");
	    else 
		    http_send_headers(fw, "text/plain");
	    write_file(fw, new_path);
    }

    http_end(fw);
}
